<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow: flow::net_flow::Congestion_control_strategy Class Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="namespaceflow.html">flow</a></li><li class="navelem"><a class="el" href="namespaceflow_1_1net__flow.html">net_flow</a></li><li class="navelem"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html">Congestion_control_strategy</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="summary">
<a href="#pub-methods">Public Member Functions</a> &#124;
<a href="#pro-methods">Protected Member Functions</a> &#124;
<a href="#pri-attribs">Private Attributes</a> &#124;
<a href="classflow_1_1net__flow_1_1Congestion__control__strategy-members.html">List of all members</a>  </div>
  <div class="headertitle"><div class="title">flow::net_flow::Congestion_control_strategy Class Reference<span class="mlabels"><span class="mlabel">abstract</span></span></div></div>
</div><!--header-->
<div class="contents">

<p>The abstract interface for a per-socket module that determines the socket's congestion control behavior.  
 <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#details">More...</a></p>

<p><code>#include &lt;<a class="el" href="cong__ctl_8hpp_source.html">cong_ctl.hpp</a>&gt;</code></p>
<div class="dynheader">
Inheritance diagram for flow::net_flow::Congestion_control_strategy:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1net__flow_1_1Congestion__control__strategy__inherit__graph.svg" width="646" height="131"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<div class="dynheader">
Collaboration diagram for flow::net_flow::Congestion_control_strategy:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1net__flow_1_1Congestion__control__strategy__coll__graph.svg" width="1398" height="387"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-methods" name="pub-methods"></a>
Public Member Functions</h2></td></tr>
<tr class="memitem:a2b9a554ac60d9fe9d6faf32433c61c86"><td class="memItemLeft" align="right" valign="top">virtual size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86">congestion_window_bytes</a> () const =0</td></tr>
<tr class="memdesc:a2b9a554ac60d9fe9d6faf32433c61c86"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns the maximal number of bytes (with respect to <code>m_data</code> field of DATA packets) that this socket should allow to be In-flight at this time.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86">More...</a><br /></td></tr>
<tr class="separator:a2b9a554ac60d9fe9d6faf32433c61c86"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a832c2c5f72635ef0d5716a9198fd16d4"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4">on_acks</a> (size_t bytes, size_t packets)</td></tr>
<tr class="memdesc:a832c2c5f72635ef0d5716a9198fd16d4"><td class="mdescLeft">&#160;</td><td class="mdescRight">Informs the congestion control strategy that 1 or more previously sent packets whose status was In-flight just received acknowledgments, thus changing their state from In-flight to Acknowledged.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4">More...</a><br /></td></tr>
<tr class="separator:a832c2c5f72635ef0d5716a9198fd16d4"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a238eb8f69e309e354d3fbc1c3017f614"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614">on_loss_event</a> (size_t bytes, size_t packets)</td></tr>
<tr class="memdesc:a238eb8f69e309e354d3fbc1c3017f614"><td class="mdescLeft">&#160;</td><td class="mdescRight">Informs the congestion control strategy that 1 or more previously sent packets whose status was In-flight have just been inferred to be Dropped by receiving acknowledgments of packets that were sent later than the now-Dropped packets.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614">More...</a><br /></td></tr>
<tr class="separator:a238eb8f69e309e354d3fbc1c3017f614"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab5a942e2097cbad4ec8ea152d40ed88a"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a">on_individual_ack</a> (const <a class="el" href="namespaceflow.html#a48799f1263cdeedec125be51a3db2b79">Fine_duration</a> &amp;packet_rtt, const size_t bytes, const size_t sent_cwnd_bytes)</td></tr>
<tr class="memdesc:ab5a942e2097cbad4ec8ea152d40ed88a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-flight is now known to have the given round trip time (RTT), via acknowledgment.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a">More...</a><br /></td></tr>
<tr class="separator:ab5a942e2097cbad4ec8ea152d40ed88a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af7543a12c99ea8d31374b064fdf13d2b"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#af7543a12c99ea8d31374b064fdf13d2b">on_drop_timeout</a> (size_t bytes, size_t packets)</td></tr>
<tr class="memdesc:af7543a12c99ea8d31374b064fdf13d2b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Informs the congestion control strategy that 1 or more previously sent packets whose status was In-flight have just been inferred to be Dropped because of the Drop Timer expiring.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#af7543a12c99ea8d31374b064fdf13d2b">More...</a><br /></td></tr>
<tr class="separator:af7543a12c99ea8d31374b064fdf13d2b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a6cecbb76a9e837824c0b820e7cc1b3b7"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a6cecbb76a9e837824c0b820e7cc1b3b7">on_idle_timeout</a> ()</td></tr>
<tr class="memdesc:a6cecbb76a9e837824c0b820e7cc1b3b7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Informs the congestion control strategy that <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> considers the connection to be "idle" by virtue of no desired send activity on the part of the user application for some period of time.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a6cecbb76a9e837824c0b820e7cc1b3b7">More...</a><br /></td></tr>
<tr class="separator:a6cecbb76a9e837824c0b820e7cc1b3b7"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="inherit_header pub_methods_classflow_1_1util_1_1Null__interface"><td colspan="2" onclick="javascript:toggleInherit('pub_methods_classflow_1_1util_1_1Null__interface')"><img src="closed.png" alt="-"/>&#160;Public Member Functions inherited from <a class="el" href="classflow_1_1util_1_1Null__interface.html">flow::util::Null_interface</a></td></tr>
<tr class="memitem:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="memItemLeft" align="right" valign="top">virtual&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Null__interface.html#a5916282577627e424a09884347eddbba">~Null_interface</a> ()=0</td></tr>
<tr class="memdesc:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="mdescLeft">&#160;</td><td class="mdescRight">Boring <code>virtual</code> destructor.  <a href="classflow_1_1util_1_1Null__interface.html#a5916282577627e424a09884347eddbba">More...</a><br /></td></tr>
<tr class="separator:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="inherit_header pub_methods_classflow_1_1log_1_1Log__context"><td colspan="2" onclick="javascript:toggleInherit('pub_methods_classflow_1_1log_1_1Log__context')"><img src="closed.png" alt="-"/>&#160;Public Member Functions inherited from <a class="el" href="classflow_1_1log_1_1Log__context.html">flow::log::Log_context</a></td></tr>
<tr class="memitem:ae7100d2dd130d8f130e3e64fdb1f4fd9 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#ae7100d2dd130d8f130e3e64fdb1f4fd9">Log_context</a> (<a class="el" href="classflow_1_1log_1_1Logger.html">Logger</a> *logger=0)</td></tr>
<tr class="memdesc:ae7100d2dd130d8f130e3e64fdb1f4fd9 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Constructs <a class="el" href="classflow_1_1log_1_1Log__context.html" title="Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...">Log_context</a> by storing the given pointer to a <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> and a null <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a>.  <a href="classflow_1_1log_1_1Log__context.html#ae7100d2dd130d8f130e3e64fdb1f4fd9">More...</a><br /></td></tr>
<tr class="separator:ae7100d2dd130d8f130e3e64fdb1f4fd9 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af1ac7f30ab442c3c6aa6079335df6c9a inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memTemplParams" colspan="2">template&lt;typename Component_payload &gt; </td></tr>
<tr class="memitem:af1ac7f30ab442c3c6aa6079335df6c9a inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memTemplItemLeft" align="right" valign="top">&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#af1ac7f30ab442c3c6aa6079335df6c9a">Log_context</a> (<a class="el" href="classflow_1_1log_1_1Logger.html">Logger</a> *logger, Component_payload component_payload)</td></tr>
<tr class="memdesc:af1ac7f30ab442c3c6aa6079335df6c9a inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Constructs <a class="el" href="classflow_1_1log_1_1Log__context.html" title="Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...">Log_context</a> by storing the given pointer to a <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> and a new <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> storing the specified generically typed payload (an <code>enum</code> value).  <a href="classflow_1_1log_1_1Log__context.html#af1ac7f30ab442c3c6aa6079335df6c9a">More...</a><br /></td></tr>
<tr class="separator:af1ac7f30ab442c3c6aa6079335df6c9a inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a5c57a7f44959a01ca9a1c948a6686cc0 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#a5c57a7f44959a01ca9a1c948a6686cc0">Log_context</a> (const <a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;src)</td></tr>
<tr class="memdesc:a5c57a7f44959a01ca9a1c948a6686cc0 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Copy constructor that stores equal <code>Logger*</code> and <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> values as the source.  <a href="classflow_1_1log_1_1Log__context.html#a5c57a7f44959a01ca9a1c948a6686cc0">More...</a><br /></td></tr>
<tr class="separator:a5c57a7f44959a01ca9a1c948a6686cc0 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a3d4e624833d96bdafa1485ffff472509 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#a3d4e624833d96bdafa1485ffff472509">Log_context</a> (<a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;&amp;src)</td></tr>
<tr class="memdesc:a3d4e624833d96bdafa1485ffff472509 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Move constructor that makes this equal to <code>src</code>, while the latter becomes as-if default-constructed.  <a href="classflow_1_1log_1_1Log__context.html#a3d4e624833d96bdafa1485ffff472509">More...</a><br /></td></tr>
<tr class="separator:a3d4e624833d96bdafa1485ffff472509 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a5d628315d5a93908d47a281980d3113e inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#a5d628315d5a93908d47a281980d3113e">operator=</a> (const <a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;src)</td></tr>
<tr class="memdesc:a5d628315d5a93908d47a281980d3113e inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Assignment operator that behaves similarly to the copy constructor.  <a href="classflow_1_1log_1_1Log__context.html#a5d628315d5a93908d47a281980d3113e">More...</a><br /></td></tr>
<tr class="separator:a5d628315d5a93908d47a281980d3113e inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:aae857197aecba8606c32296bc7bec308 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#aae857197aecba8606c32296bc7bec308">operator=</a> (<a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;&amp;src)</td></tr>
<tr class="memdesc:aae857197aecba8606c32296bc7bec308 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Move assignment operator that behaves similarly to the move constructor.  <a href="classflow_1_1log_1_1Log__context.html#aae857197aecba8606c32296bc7bec308">More...</a><br /></td></tr>
<tr class="separator:aae857197aecba8606c32296bc7bec308 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:aa6bb8e4250586425631ef80063caf155 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#aa6bb8e4250586425631ef80063caf155">swap</a> (<a class="el" href="classflow_1_1log_1_1Log__context.html">Log_context</a> &amp;other)</td></tr>
<tr class="memdesc:aa6bb8e4250586425631ef80063caf155 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Swaps <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> pointers and <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> objects held by <code>*this</code> and <code>other</code>.  <a href="classflow_1_1log_1_1Log__context.html#aa6bb8e4250586425631ef80063caf155">More...</a><br /></td></tr>
<tr class="separator:aa6bb8e4250586425631ef80063caf155 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af4db395042b065b00398cd59845dcb4d inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classflow_1_1log_1_1Logger.html">Logger</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#af4db395042b065b00398cd59845dcb4d">get_logger</a> () const</td></tr>
<tr class="memdesc:af4db395042b065b00398cd59845dcb4d inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns the stored <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> pointer, particularly as many <code>FLOW_LOG_*()</code> macros expect.  <a href="classflow_1_1log_1_1Log__context.html#af4db395042b065b00398cd59845dcb4d">More...</a><br /></td></tr>
<tr class="separator:af4db395042b065b00398cd59845dcb4d inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a8a5fef42dc2cedf3c0d1a6e83beb2948 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="classflow_1_1log_1_1Component.html">Component</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Log__context.html#a8a5fef42dc2cedf3c0d1a6e83beb2948">get_log_component</a> () const</td></tr>
<tr class="memdesc:a8a5fef42dc2cedf3c0d1a6e83beb2948 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns reference to the stored <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> object, particularly as many <code>FLOW_LOG_*()</code> macros expect.  <a href="classflow_1_1log_1_1Log__context.html#a8a5fef42dc2cedf3c0d1a6e83beb2948">More...</a><br /></td></tr>
<tr class="separator:a8a5fef42dc2cedf3c0d1a6e83beb2948 inherit pub_methods_classflow_1_1log_1_1Log__context"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pro-methods" name="pro-methods"></a>
Protected Member Functions</h2></td></tr>
<tr class="memitem:a0eacd984fd4e7d5ad3c30a59082ac95b"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a0eacd984fd4e7d5ad3c30a59082ac95b">Congestion_control_strategy</a> (<a class="el" href="classflow_1_1log_1_1Logger.html">log::Logger</a> *logger_ptr, <a class="el" href="classflow_1_1util_1_1Shared__ptr__alias__holder.html#aef7998db71c60eeb5d1e3d1a97c14886">Peer_socket::Const_ptr</a> sock)</td></tr>
<tr class="memdesc:a0eacd984fd4e7d5ad3c30a59082ac95b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Constructs object by setting up logging and saving a pointer to the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a0eacd984fd4e7d5ad3c30a59082ac95b">More...</a><br /></td></tr>
<tr class="separator:a0eacd984fd4e7d5ad3c30a59082ac95b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a3e9786f9e5f170ca23135a2a815bc3f4"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classflow_1_1util_1_1Shared__ptr__alias__holder.html#aef7998db71c60eeb5d1e3d1a97c14886">Peer_socket::Const_ptr</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a3e9786f9e5f170ca23135a2a815bc3f4">socket</a> () const</td></tr>
<tr class="memdesc:a3e9786f9e5f170ca23135a2a815bc3f4"><td class="mdescLeft">&#160;</td><td class="mdescRight">Utility for subclasses that returns a handle to the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>.  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a3e9786f9e5f170ca23135a2a815bc3f4">More...</a><br /></td></tr>
<tr class="separator:a3e9786f9e5f170ca23135a2a815bc3f4"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pri-attribs" name="pri-attribs"></a>
Private Attributes</h2></td></tr>
<tr class="memitem:a1da6833e0c23d111432cbdd3f5451180"><td class="memItemLeft" align="right" valign="top">boost::weak_ptr&lt; Peer_socket::Const_ptr::element_type &gt;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a1da6833e0c23d111432cbdd3f5451180">m_sock</a></td></tr>
<tr class="memdesc:a1da6833e0c23d111432cbdd3f5451180"><td class="mdescLeft">&#160;</td><td class="mdescRight">The containing socket (read-only access).  <a href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a1da6833e0c23d111432cbdd3f5451180">More...</a><br /></td></tr>
<tr class="separator:a1da6833e0c23d111432cbdd3f5451180"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><p >The abstract interface for a per-socket module that determines the socket's congestion control behavior. </p>
<p >Each <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> is to create an instance of a concrete subclass of this class, thus determining that socket's can-send policy.</p>
<h3>Congestion control</h3>
<p >This term refers to the process of deciding when to send data, assuming data are available to send. In a magic world we could send all available data immediately upon it becoming available, but in the real world doing so at a high volume or in poor networks will eventually lead to packets being dropped somewhere along the way or at the destination. To determine whether we can send data (if available), we maintain <code>m_snd_flying_bytes</code> (how much we think is currently In-flight, i.e. sent by us but not yet Acknowledged by the receiver or Dropped by the network or receiver) and CWND (how much data we think the route, or pipe, can hold In-flight without dropping too much). Basically if <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#ae870847f024fca7109c15557bb165480" title="The number of bytes contained in all In-flight packets, used at least for comparison against the cong...">Peer_socket::m_snd_flying_bytes</a> &lt; CWND, data could be sent.</p>
<p >How to determine CWND though? That is the main question in congestion control. In <code><a class="el" href="namespaceflow_1_1net__flow.html" title="Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...">net_flow</a></code>, the <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> data member <code><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> sock-&gt;m_cong_ctl</code> provides the API that returns CWND (how it does so depends on the real type implementing that interface). In order to compute/update CWND, <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> and all subclasses have <code>const</code> access to <code>sock</code>. Since it does not get its own thread, it needs to be informed of various events on <code>sock</code> (ACKs, timeouts) so that it can potentially recompute its CWND. Thus the interface consists of, basically: <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> (obtain CWND for comparison to In-flight bytes in <code>can_send()</code>); and <code>on_...()</code> methods to effect change in the internally stored CWND.</p>
<h3>Object life cycle</h3>
<p >There is a strict 1-to-1 relationship between one <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> instance and one <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>. A <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> is created shortly after <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> is and is saved inside the latter. Conversely a pointer to the <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> is stored inside the <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a>. Many congestion control algorithms need (read-only) access to the innards of a socket; for example they may frequently access <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#ad08b53052e7eedfa7a925258f5ef1cba" title="Estimated current round trip time of packets, computed as a smooth value over the past individual RTT...">Peer_socket::m_snd_smoothed_round_trip_time</a> (SRTT) for various calculations. The containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> must exist at all times while <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> exists. Informally it's recommended that <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> destructor or other method deletes its <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> instance when it is no longer needed.</p>
<h3>Functionality provided by this class</h3>
<p >The main functionality is the aforementioned interface.</p>
<p >Secondarily, this main functionality is implemented as do-nothing methods (as opposed to pure methods). Finally, the class stores a pointer to the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>, as a convenience for subclasses.</p>
<h3>General design note</h3>
<p >TCP RFCs like RFC 5681 tend to present a monolithic congestion control algorithm. For example, Fast Retransmit/Fast Recovery is described as one combined algorithm in RFC 5681-3.2. It doesn't describe loss detection (3 dupe-ACKs), retransmission (send first segment found to be lost), congestion window adjustment and loss recovery (CWND/SSTHRESH halving, CWND inflation/deflation) as belonging to separate modules working together but rather as one monolithic algorithm. The design we use here is an attempt to separate those things into distinct modules (classes or at least methods) that work together but are abstractly separated within reason. This should result in cleaner, clearer, more maintainable code. Namely, retransmission and loss detection are (separate) in <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a>, while CWND manipulations are in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a>. <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a>'s focus is, as narrowly as possible, to compute CWND based on inputs from <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a>. This may run counter to the how a given RFC is written, since the part of "Reno" involving counting dupe-ACKs is not at all part of the Reno congestion control module (<a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html" title="Classic congestion control, based on Reno (TCP RFC 5681), with congestion avoidance,...">Congestion_control_classic</a>) but directly inside <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> instead.</p>
<h3>Assumptions about outside worl</h3>
<p >To support an efficient and clean design, it's important to cleanly delineate the level of abstraction involved in the <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> class hierarchy. How stand-alone is the hierarchy? What assumptions does it make about its underlying socket's state? The answer is as follows. The hierarchy only cares about</p>
<ol type="1">
<li>events (<code>on_...()</code> methods like <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a>) that occur on the socket (it must know about EVERY occurrence of each event as soon as it occurs);</li>
<li>certain state of the socket (such as <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#ae870847f024fca7109c15557bb165480" title="The number of bytes contained in all In-flight packets, used at least for comparison against the cong...">Peer_socket::m_snd_flying_bytes</a>).</li>
</ol>
<p >The documentation for each <code>on_...()</code> method must therefore exactly specify what the event means. Similarly, either the doc header for the appropriate method or the class doc header must specify what, if any, <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> state must be set and how. That said, even with clean documentation, the key point is that the <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> hierarchy must work TOGETHER with the <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> and <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>; there is no way to make the programmer of a congestion control module be able to ignore the relevant details (like how ACKs are generated and handled) of <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> and <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>. The reverse is not true; congestion control MUST be a black box to the <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> code; it can provide inputs (as events and arguments to the <code>on_...()</code> calls; and as read-only state in <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>) to <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> objects, but it must have no access (read or write) to the latter's internals. This philosophy is loosely followed in the Linux kernel code, though in my opinion Linux kernel code (in this case) is not quite as straightforward or clean as it could be (which I humbly tried to improve upon here). Bottom line:</p>
<ol type="1">
<li><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> and subclasses are a black box to Node/Peer_socket code (no access to internals; access only to constructors/destructor and API).</li>
<li><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> and subclasses have <code>const</code> (!) <code>friend</code> access to <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> internals.</li>
<li>The programmer of any <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> subclass must assume a certain event model to be followed by <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a>. This model is to be explicitly explained in the doc headers for the various <code>on_...()</code> methods. <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> must call the <code>on_...()</code> methods as soon as it detects the appropriate events, and it should aim to detect them as soon as possible after they occur.</li>
<li>The programmer of any <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> subclass may assume the existence and meaning of certain state of <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>, which she can use to make internal computations. Any such state (i.e., in addition to the on-event calls, and their arguments, in (3)) must be explicitly documented in the class or method doc headers.</li>
</ol>
<h3>Choice of congestion window units</h3>
<p >We choose bytes, instead of multiples of max-block-size (in TCP, this would be maximum segment size [MSS]). Either would have been feasible. TCP RFCs use bytes (even if most of the math involves incrementing/decrementing in multiples of MSS); so does at least the canonical BSD TCP implementation (Stevens/Wright, TCP/IP Illustrated Vol. 2) from the early 90s (not sure about modern version). Linux TCP uses multiples of MSS, as do many papers on alternative congestion control methods. Reasoning for our choice of bytes: First, the particular congestion control implementation can still do all internal math in multiples of max-block-size (if desired) and then just multiply by that in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> at the last moment. Second, I've found that certain algorithms, namely Appropriate Byte Counting, are difficult to perform in terms of multiples while staying true to the algorithm as written (one either has to lose some precision or maintain fractional CWND parts which cancels out some of the simplicity in using the multiples-of-MSS accounting method). Thus it seemed natural to go with the more flexible approach. The only cost of that is that <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a>, when using <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a>, must be ready for it to return a non-multiple-of-max-block-size value and act properly. This is not at all a major challenge in practice.</p>
<h3>Terminology</h3>
<p >In doc comments throughout this class hierarchy, the terms "simultaneously," "immediately," and "as soon as" are to be interpreted as follows: Within a non-blocking amount of time. Note that that is not the same as literally "as soon as possible," because for efficiency the <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> implementation may choose to perform other non-blocking actions first. For example, <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> is to be called "as soon as" a packet acknowledgment is received, but the <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> can and should first accumulate all other acks that have already arrived, and only then call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> for all of them. Thus, in practice, in the <code><a class="el" href="namespaceflow_1_1net__flow.html" title="Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...">net_flow</a></code> implementation, "immediately/as soon
as/simultaneously" is the same as "within the same boost.asio handler invocation," because each handler is written to complete without blocking (sleeping).</p>
<h3>Thread safety</h3>
<p >Unless stated otherwise, a <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> object is to be accessed from the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>'s <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a>'s thread W only.</p>
<p >How to add a new <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> subclass? First write the code to above spec (using existing strategies as a basis &ndash; especially <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html" title="Classic congestion control, based on Reno (TCP RFC 5681), with congestion avoidance,...">Congestion_control_classic</a>, upon which most others are usually based) and put it in the self-explanatory location. Next, add it to the socket option machinery, so that it can be programmatically selected for a given <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> or <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>, or selected by the user via a config file or command line, if the application-layer programmer so chooses. To do so, add it to the following locations (by analogy with existing ones):</p>
<ul>
<li><code>enum Peer_socket_options::Congestion_control_strategy_choice::Congestion_control_strategy_choice.</code></li>
<li><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__selector.html#aaa68a02633d67e11bdf7e8e722370ca2" title="Maps each ID to the corresponding Strategy_choice enum value.">Congestion_control_selector::S_ID_TO_STRATEGY_MAP</a> <code>static</code> initializer.</li>
<li><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__selector.html#a590c0877dd8751b190173ed9f01d23c7" title="The inverse of S_ID_TO_STRATEGY_MAP.">Congestion_control_selector::S_STRATEGY_TO_ID_MAP</a> <code>static</code> initializer.</li>
<li>Factory method <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__selector.html#a52eee18d41c3f9cc7d6c48b766a7919f" title="Factory method that, given an enum identifying the desired strategy, allocates the appropriate Conges...">Congestion_control_selector::create_strategy()</a>.</li>
</ul>
<p >Voila! You can now use the new congestion control algorithm.</p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000059">Todo:</a></b></dt><dd>Tuck away all congestion control-related symbols into new <code>namespace cong_ctl</code>? </dd></dl>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8hpp_source.html#l00176">176</a> of file <a class="el" href="cong__ctl_8hpp_source.html">cong_ctl.hpp</a>.</p>
</div><h2 class="groupheader">Constructor &amp; Destructor Documentation</h2>
<a id="a0eacd984fd4e7d5ad3c30a59082ac95b" name="a0eacd984fd4e7d5ad3c30a59082ac95b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a0eacd984fd4e7d5ad3c30a59082ac95b">&#9670;&nbsp;</a></span>Congestion_control_strategy()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">flow::net_flow::Congestion_control_strategy::Congestion_control_strategy </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classflow_1_1log_1_1Logger.html">log::Logger</a> *&#160;</td>
          <td class="paramname"><em>logger_ptr</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="classflow_1_1util_1_1Shared__ptr__alias__holder.html#aef7998db71c60eeb5d1e3d1a97c14886">Peer_socket::Const_ptr</a>&#160;</td>
          <td class="paramname"><em>sock</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">explicit</span><span class="mlabel">protected</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Constructs object by setting up logging and saving a pointer to the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>. </p>
<p >Only a weak pointer of <code>sock</code> is stored: the <code>shared_ptr</code> itself is not saved, so the reference count of <code>sock</code> does not increase. This avoids a circular <code>shared_ptr</code> situation.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">logger_ptr</td><td>The Logger implementation to use subsequently. </td></tr>
    <tr><td class="paramname">sock</td><td>The <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> for which this module will control congestion policy. </td></tr>
  </table>
  </dd>
</dl>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00029">29</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

</div>
</div>
<h2 class="groupheader">Member Function Documentation</h2>
<a id="a2b9a554ac60d9fe9d6faf32433c61c86" name="a2b9a554ac60d9fe9d6faf32433c61c86"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a2b9a554ac60d9fe9d6faf32433c61c86">&#9670;&nbsp;</a></span>congestion_window_bytes()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual size_t flow::net_flow::Congestion_control_strategy::congestion_window_bytes </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td> const</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Returns the maximal number of bytes (with respect to <code>m_data</code> field of DATA packets) that this socket should allow to be In-flight at this time. </p>
<p >Bytes, if available, can be sent if and only if this value is greater than the # of In-flight bytes at this time.</p>
<p >This is pure. Each specific congestion control strategy must implement this.</p>
<dl class="section note"><dt>Note</dt><dd>For definition of In-flight bytes, see <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a>. </dd></dl>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html#a98ee7d39ccbacacaec6b9e0deff1e6b1">flow::net_flow::Congestion_control_classic</a>, and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic__with__bandwidth__est.html#af49a3fe6d8bb1ec32ac245faed17e842">flow::net_flow::Congestion_control_classic_with_bandwidth_est</a>.</p>

</div>
</div>
<a id="a832c2c5f72635ef0d5716a9198fd16d4" name="a832c2c5f72635ef0d5716a9198fd16d4"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a832c2c5f72635ef0d5716a9198fd16d4">&#9670;&nbsp;</a></span>on_acks()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::net_flow::Congestion_control_strategy::on_acks </td>
          <td>(</td>
          <td class="paramtype">size_t&#160;</td>
          <td class="paramname"><em>bytes</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">size_t&#160;</td>
          <td class="paramname"><em>packets</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Informs the congestion control strategy that 1 or more previously sent packets whose status was In-flight just received acknowledgments, thus changing their state from In-flight to Acknowledged. </p>
<p >For efficiency and simplicity of behavior, <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> should be called as few times as possible while still satisfying the requirement in the previous sentence. That is, suppose acknowledgments for N packets were received simultaneously. Then <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> must be called one time, with the "packets" argument equal to N &ndash; not, say, N times with <code>packets == 1</code>.</p>
<p >The acknowledgments that led to this <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> call also results in 1 or more individual <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> calls covering each individual packet. You MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> and THEN call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a>.</p>
<p >If the acknowledgment group that led to <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> also exposed the loss of some packets, i.e., if the criteria for <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> also hold, then you MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> and THEN call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a>. (Informal reasoning: the ACKs are exposing drop(s) that occurred in the past, chronologically before the ACKed packets arrived. Thus the events should fire in that order.)</p>
<p >You MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> AFTER <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> state (<a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> et al) has been updated to reflect the acknowledgments being reported here.</p>
<p >Assumptions about ACK sender (DATA receiver): It is assumed that:</p>
<ul>
<li>Every DATA packet is acknowledged at most T after it was received, where T is some reasonably small constant time period (see Node::S_DELAYED_ACK_TIMER_PERIOD). (I.e., an ACK may be delayed w/r/t DATA reception but only up to a certain delay T.)</li>
<li>All received but not-yet-acked DATA packets are acknowledged as soon as there are at least Node::S_MAX_FULL_PACKETS_BEFORE_ACK_SEND * max-block-size bytes in the received but not-yet-acked DATA packets. (I.e., every 2nd DATA packet forces an immediate ACK to be sent.)</li>
<li>If, after the DATA receiver has processed all DATA packets that were received simultaneously, at least one of those DATA packets has a higher sequence number than a datum the receiver has not yet received, then all received but not-yet-acked DATA packets are acknowledged. (I.e., every out-of-order DATA packet forces an immediate ACK to be sent.)</li>
</ul>
<dl class="section note"><dt>Note</dt><dd><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> may return a higher value after this call. You should check <code>can_send()</code>. </dd>
<dd>
Acknowledgments of data that are not currently In-flight due to being Dropped (a/k/a late ACKs) or Acknowledged (i.e., duplicate ACKs) must NOT be passed to this method. </dd>
<dd>
If an acknowledgment for packet P transmission N is received, while packet P transmission M != N is the one currently In-flight (i.e., packet was retransmitted, but the earlier incarnation was late-acked), such acknowledgments must NOT be passed to this method. We may reconsider this in the future. </dd>
<dd>
<a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> makes no assumptions about how the reported individual packet acks were packaged by the ACK sender into actual ACK packets (how many ACKs there were, etc.). It just assumes every individual acknowledgment is reported to <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> as soon as possible and grouped into as few <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> calls as possible. </dd>
<dd>
For definition of In-flight, Acknowledged, and Dropped bytes, see <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> and <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a2db7d11ece920d4adcacd00eaa2253fd" title="The collection of all In-flight packets (including those queued up to send in pacing module),...">Peer_socket::m_snd_flying_pkts_by_seq_num</a>.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">bytes</td><td>The sum of the number of bytes in the user data fields of the packets that have been Acknowledged. Must not be zero. </td></tr>
    <tr><td class="paramname">packets</td><td>The number of packets thus Acknowledged. </td></tr>
  </table>
  </dd>
</dl>

<p>Reimplemented in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html#a34b8ef88093f082df7a935bbebfae2f3">flow::net_flow::Congestion_control_classic</a>, and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic__with__bandwidth__est.html#a83ee8438d6033c26a6af03b9dd173dc3">flow::net_flow::Congestion_control_classic_with_bandwidth_est</a>.</p>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00036">36</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

</div>
</div>
<a id="af7543a12c99ea8d31374b064fdf13d2b" name="af7543a12c99ea8d31374b064fdf13d2b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#af7543a12c99ea8d31374b064fdf13d2b">&#9670;&nbsp;</a></span>on_drop_timeout()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::net_flow::Congestion_control_strategy::on_drop_timeout </td>
          <td>(</td>
          <td class="paramtype">size_t&#160;</td>
          <td class="paramname"><em>bytes</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">size_t&#160;</td>
          <td class="paramname"><em>packets</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Informs the congestion control strategy that 1 or more previously sent packets whose status was In-flight have just been inferred to be Dropped because of the Drop Timer expiring. </p>
<p >A formal description of what "Drop Timer expiring" means is too large to put here, and there are many different ways to do it. See class <a class="el" href="classflow_1_1net__flow_1_1Drop__timer.html" title="Internal net_flow class that maintains the Drop Timer for DATA packet(s) to have been sent out over a...">Drop_timer</a> and the code that uses it. Formally, we expect that one Drop Timer is running if and only if there is at least one packet In-flight, and that that Drop Timer expiring implies the immediate conversion of at least one packet from In-flight to Dropped. We also expect that, informally, the Drop Timeout indicates serious loss events and is the 2nd and last resort in detecting loss, the main (and more likely to trigger first) one being <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a>.</p>
<p >You MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#af7543a12c99ea8d31374b064fdf13d2b" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_drop_timeout()</a> AFTER <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> state (<a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> et al) has been updated to reflect the drops being reported here.</p>
<dl class="section note"><dt>Note</dt><dd><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> WILL NOT return a higher value after this call. You need not call <code>can_send()</code>. </dd>
<dd>
For definition of In-flight, Acknowledged, and Dropped bytes, see <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> and <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a2db7d11ece920d4adcacd00eaa2253fd" title="The collection of all In-flight packets (including those queued up to send in pacing module),...">Peer_socket::m_snd_flying_pkts_by_seq_num</a>. </dd>
<dd>
This is analogous to the Retransmit Timeout (RTO) algorithm in classic TCP congestion control (e.g., RFCs 5681 and 6298).</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">bytes</td><td>The sum of the number of bytes in the user data fields of the packets that have been Dropped with this Drop Timeout. Must not be zero. </td></tr>
    <tr><td class="paramname">packets</td><td>The number of packets thus Dropped. </td></tr>
  </table>
  </dd>
</dl>

<p>Reimplemented in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html#a59148ce4dafea4063b6992b9670909dc">flow::net_flow::Congestion_control_classic</a>, and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic__with__bandwidth__est.html#a3358f8b8700d5427a5163f2f480b2e8d">flow::net_flow::Congestion_control_classic_with_bandwidth_est</a>.</p>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00047">47</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

</div>
</div>
<a id="a6cecbb76a9e837824c0b820e7cc1b3b7" name="a6cecbb76a9e837824c0b820e7cc1b3b7"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a6cecbb76a9e837824c0b820e7cc1b3b7">&#9670;&nbsp;</a></span>on_idle_timeout()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::net_flow::Congestion_control_strategy::on_idle_timeout </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Informs the congestion control strategy that <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">Node</a> considers the connection to be "idle" by virtue of no desired send activity on the part of the user application for some period of time. </p>
<p >Informally, this means "the user hasn't wanted to send anything for a while, so you may want to
update your CWND calculations based on that fact, as it's likely you have obsolete information
about the connection." For example, if a connection has been idle for 5 minutes, then there have been no ACKs for a while, and since ACKs typically are the tool used to gather congestion data and thus compute CWND, the internal CWND may be reset to its default initial value within <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a6cecbb76a9e837824c0b820e7cc1b3b7" title="Informs the congestion control strategy that Node considers the connection to be &quot;idle&quot; by virtue of ...">on_idle_timeout()</a>.</p>
<p >The formal definition of Idle Timeout is the one used in <a class="el" href="classflow_1_1net__flow_1_1Node.html#a10a92f11a2c9f218cdd9a55f282e79b1" title="Thread W implemention of send(): synchronously or asynchronously send the contents of sock-&gt;m_snd_buf...">Node::send_worker()</a>. Short version: an Idle Timeout occurs T after the last packet to be sent out, where T is the Drop Timeout (see <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#af7543a12c99ea8d31374b064fdf13d2b" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_drop_timeout()</a>).</p>
<dl class="section note"><dt>Note</dt><dd><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> WILL NOT return a higher value after this call. You need not call <code>can_send()</code>. </dd>
<dd>
This is analogous to the "Restarting Idle Connections" algorithm in classic TCP congestion control (RFC 5681-4.1). </dd></dl>

<p>Reimplemented in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html#a588baa530b660a3437d3a39d68b16404">flow::net_flow::Congestion_control_classic</a>, and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic__with__bandwidth__est.html#a461064f1ff0303cded61131df593599a">flow::net_flow::Congestion_control_classic_with_bandwidth_est</a>.</p>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00053">53</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

</div>
</div>
<a id="ab5a942e2097cbad4ec8ea152d40ed88a" name="ab5a942e2097cbad4ec8ea152d40ed88a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab5a942e2097cbad4ec8ea152d40ed88a">&#9670;&nbsp;</a></span>on_individual_ack()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::net_flow::Congestion_control_strategy::on_individual_ack </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="namespaceflow.html#a48799f1263cdeedec125be51a3db2b79">Fine_duration</a> &amp;&#160;</td>
          <td class="paramname"><em>packet_rtt</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const size_t&#160;</td>
          <td class="paramname"><em>bytes</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const size_t&#160;</td>
          <td class="paramname"><em>sent_cwnd_bytes</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-flight is now known to have the given round trip time (RTT), via acknowledgment. </p>
<p >In other words, this informs congestion control of each valid individual-packet acknowledgment of a packet that was In-flight at time of acknowledgment.</p>
<p >The acknowledgment that led to the given individual RTT measurement also results in a consolidated <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> call that covers that packet and all other packets acked simultaneously; you MUST call this <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> and THEN call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a>. <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> should be called in the order of receipt of the containing ACK that led to the RTT measurement; if two RTTs are generated from one ACK, the tie should be broken in the order of appearance within the ACK.</p>
<p >If the acknowledgment group that led to <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> also exposed the loss of some packets, i.e., if the criteria for <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> also hold, then you MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> and THEN call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a>. (Informal reasoning: the ACKs are exposing drop(s) that occurred in the past, chronologically before the ACKed packets arrived. Thus the events should fire in that order.)</p>
<p >You MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> AFTER <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> state (<a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> et al) has been updated to reflect the acknowledgments being reported here.</p>
<p >Assumptions about RTT value: The RTT value is assumed to include only the time spent in transit from sender to receiver plus the time the ACK spent in transit from receiver to sender. Any delay (such as ACK delay) adding to the total time from sending DATA to receiving ACK is <em>not</em> to be included in the RTT. RTT is meant to measure network conditions/capacity.</p>
<dl class="section note"><dt>Note</dt><dd><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> may return a higher value after this call, but you should wait to query it until after calling <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> for the entire round of acknowledgments being handled. </dd>
<dd>
Acknowledgments of data that is not currently In-flight due to being Dropped (a/k/a late ACKs) or Acknowledged (i.e., duplicate ACKs) must NOT be passed to this method. </dd>
<dd>
If an acknowledgment for packet P transmission N is received, while packet P transmission M != N is the one currently In-flight (i.e., packet was retransmitted, but the earlier incarnation was late-acked), such acknowledgments must NOT be passed to this method. We may reconsider this in the future. </dd>
<dd>
For definition of In-flight, Acknowledged, and Dropped bytes, see <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> and <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a>.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">packet_rtt</td><td>Round trip time of an individual packet. </td></tr>
    <tr><td class="paramname">bytes</td><td>The number of bytes of user data corresponding to this RTT sample (i.e., # of bytes acknowledged in the acknowledged packet). </td></tr>
    <tr><td class="paramname">sent_cwnd_bytes</td><td><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> when acked DATA packet was sent. </td></tr>
  </table>
  </dd>
</dl>

<p>Reimplemented in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic__with__bandwidth__est.html#a8d0e32a67aa333ab15a5b166a2913260">flow::net_flow::Congestion_control_classic_with_bandwidth_est</a>.</p>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00058">58</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

</div>
</div>
<a id="a238eb8f69e309e354d3fbc1c3017f614" name="a238eb8f69e309e354d3fbc1c3017f614"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a238eb8f69e309e354d3fbc1c3017f614">&#9670;&nbsp;</a></span>on_loss_event()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::net_flow::Congestion_control_strategy::on_loss_event </td>
          <td>(</td>
          <td class="paramtype">size_t&#160;</td>
          <td class="paramname"><em>bytes</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">size_t&#160;</td>
          <td class="paramname"><em>packets</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Informs the congestion control strategy that 1 or more previously sent packets whose status was In-flight have just been inferred to be Dropped by receiving acknowledgments of packets that were sent later than the now-Dropped packets. </p>
<p >For efficiency and simplicity of behavior, <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> should be called as few times as possible while still satisfying the requirement in the previous sentence. That is, suppose acknowledgments for N packets were received simultaneously thus exposing M packets as dropped. Then <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> must be called one time, with the "packets" argument equal to M and not, say, M times with packets == 1.</p>
<p >An important addendum to the above rule is as follows. You MUST NOT call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a>, if the Dropped packets which would have led to this call are part of the same loss event as those in the preceding <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> call. How is "part of the same loss event" defined? This is formally defined within the large comment header at the top of <a class="el" href="classflow_1_1net__flow_1_1Node.html#a136d9ccd25634cee2955ea79ae829006" title="Helper of perform_accumulated_on_recv_tasks() that handles any incoming acknowledgments and rcv_wnd u...">Node::handle_accumulated_acks()</a>. The informal short version: If the new Dropped packets were sent roughly within an RTT of those in the previous <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a>, then do not call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a>. The informal reasoning for this is to avoid sharply reducing <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> value due to 2+ groups of acks that arrive close to each other but really indicate just 1 loss event nevertheless repeatedly reducing CWND.</p>
<p ><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> must be called BEFORE <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a> and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> are called for the ack group that exposed the lost packets. See <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a832c2c5f72635ef0d5716a9198fd16d4" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_acks()</a> and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#ab5a942e2097cbad4ec8ea152d40ed88a" title="Informs the congestion control strategy that exactly 1 previously sent packet whose status was In-fli...">on_individual_ack()</a>.</p>
<p >You MUST call <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a238eb8f69e309e354d3fbc1c3017f614" title="Informs the congestion control strategy that 1 or more previously sent packets whose status was In-fl...">on_loss_event()</a> AFTER <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> state (<code>m_snd_flying_pkts_by_sent_when</code> et al) has been updated to reflect the drops being reported here.</p>
<dl class="section note"><dt>Note</dt><dd><a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html#a2b9a554ac60d9fe9d6faf32433c61c86" title="Returns the maximal number of bytes (with respect to m_data field of DATA packets) that this socket s...">congestion_window_bytes()</a> WILL NOT return a higher value after this call. You need not call <code>can_send()</code>. </dd>
<dd>
For definition of In-flight, Acknowledged, and Dropped bytes, see <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a> and <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html#a5ea56c54a98289211fef4a672432a2ad" title="The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...">Peer_socket::m_snd_flying_pkts_by_sent_when</a>. </dd>
<dd>
This is analogous to the 3-dupe-ACKs part of the Fast Retransmit/Recovery algorithm in classic TCP congestion control (e.g., RFC 5681).</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">bytes</td><td>The sum of the number of bytes in the user data fields of the packets that have been Dropped. Must not be zero. </td></tr>
    <tr><td class="paramname">packets</td><td>The number of packets thus Dropped. </td></tr>
  </table>
  </dd>
</dl>

<p>Reimplemented in <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic.html#af2340e68dbdbb8d6065ae487b05074be">flow::net_flow::Congestion_control_classic</a>, and <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__classic__with__bandwidth__est.html#a942ce2561d6d2bbbb8faa8160a772416">flow::net_flow::Congestion_control_classic_with_bandwidth_est</a>.</p>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00041">41</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

</div>
</div>
<a id="a3e9786f9e5f170ca23135a2a815bc3f4" name="a3e9786f9e5f170ca23135a2a815bc3f4"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a3e9786f9e5f170ca23135a2a815bc3f4">&#9670;&nbsp;</a></span>socket()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classflow_1_1util_1_1Shared__ptr__alias__holder.html#aef7998db71c60eeb5d1e3d1a97c14886">Peer_socket::Const_ptr</a> flow::net_flow::Congestion_control_strategy::socket </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td> const</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">protected</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Utility for subclasses that returns a handle to the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>. </p>
<p >If somehow the containing <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> has been deleted, <code>assert()</code> trips.</p>
<dl class="section return"><dt>Returns</dt><dd>Ditto. </dd></dl>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8cpp_source.html#l00063">63</a> of file <a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a>.</p>

<p class="reference">References <a class="el" href="cong__ctl_8hpp_source.html#l00433">m_sock</a>.</p>

<p class="reference">Referenced by <a class="el" href="cong__ctl__classic__bw_8cpp_source.html#l00173">flow::net_flow::Congestion_control_classic_with_bandwidth_est::congestion_window_adjusted_bytes()</a>, <a class="el" href="cong__ctl__classic_8cpp_source.html#l00164">flow::net_flow::Congestion_control_classic::congestion_window_decay()</a>, <a class="el" href="cong__ctl__classic_8cpp_source.html#l00126">flow::net_flow::Congestion_control_classic::on_drop_timeout()</a>, <a class="el" href="cong__ctl__classic__bw_8cpp_source.html#l00137">flow::net_flow::Congestion_control_classic_with_bandwidth_est::on_drop_timeout()</a>, <a class="el" href="cong__ctl__classic__bw_8cpp_source.html#l00051">flow::net_flow::Congestion_control_classic_with_bandwidth_est::on_individual_ack()</a>, <a class="el" href="cong__ctl__classic_8cpp_source.html#l00046">flow::net_flow::Congestion_control_classic::on_loss_event()</a>, and <a class="el" href="cong__ctl__classic__bw_8cpp_source.html#l00103">flow::net_flow::Congestion_control_classic_with_bandwidth_est::on_loss_event()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1net__flow_1_1Congestion__control__strategy_a3e9786f9e5f170ca23135a2a815bc3f4_icgraph.svg" width="720" height="404"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<h2 class="groupheader">Member Data Documentation</h2>
<a id="a1da6833e0c23d111432cbdd3f5451180" name="a1da6833e0c23d111432cbdd3f5451180"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a1da6833e0c23d111432cbdd3f5451180">&#9670;&nbsp;</a></span>m_sock</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">boost::weak_ptr&lt;Peer_socket::Const_ptr::element_type&gt; flow::net_flow::Congestion_control_strategy::m_sock</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>The containing socket (read-only access). </p>
<p >Implementation may rely on various state stored inside the pointed-to <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>.</p>
<p >Why <code>weak_ptr</code>? If we stored a <code>shared_ptr</code> (<a class="el" href="classflow_1_1util_1_1Shared__ptr__alias__holder.html#aef7998db71c60eeb5d1e3d1a97c14886" title="Short-hand for ref-counted pointer to immutable values of type Target_type::element_type (a-la T cons...">Peer_socket::Const_ptr</a>) then something would have to delete this <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> object before the pointee <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>'s ref-count could drop to zero and it too could be deleted; this is undesirable since the guy that would want to delete this <a class="el" href="classflow_1_1net__flow_1_1Congestion__control__strategy.html" title="The abstract interface for a per-socket module that determines the socket&#39;s congestion control behavi...">Congestion_control_strategy</a> is <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a>'s destructor itself (standard circular <code>shared_ptr</code> problem). If we stored a raw const <code>Peer_socket*</code> pointer instead, that would be fine. However, using a <code>weak_ptr</code> allows us to <code>assert()</code> in a civilized way if the underlying <a class="el" href="classflow_1_1net__flow_1_1Peer__socket.html" title="A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...">Peer_socket</a> had been deleted (instead of crashing due to accessing deleted memory as we would with a raw pointer). This isn't really a big deal, since hopefully our code will be written properly to avoid this, but this is just a little cleaner. </p>

<p class="definition">Definition at line <a class="el" href="cong__ctl_8hpp_source.html#l00433">433</a> of file <a class="el" href="cong__ctl_8hpp_source.html">cong_ctl.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="cong__ctl_8cpp_source.html#l00063">socket()</a>.</p>

</div>
</div>
<hr/>The documentation for this class was generated from the following files:<ul>
<li>net_flow/detail/<a class="el" href="cong__ctl_8hpp_source.html">cong_ctl.hpp</a></li>
<li>net_flow/detail/<a class="el" href="cong__ctl_8cpp_source.html">cong_ctl.cpp</a></li>
</ul>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Mar 28 2025 22:55:35 for Flow by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
